﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Text;
using System.Web.UI;
using TA.Turbo.Design;

namespace TA.Turbo.Controls
{
	/// <summary>
	/// Outputs a collection of data objects using a table layout.
	/// </summary>
	[PersistChildren(false)]
	[ParseChildren(true)]
	public class Grid : Repeater
	{
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		public Grid()
		{
			//ShowHeader = true;
			//ShowFooter = true;
		}
		#endregion
		#region PROPS
		/// <summary>
		/// Specify columns that will be displayed with data.
		/// </summary>
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[Editor(typeof(GridColumnsEditor), typeof(UITypeEditor))]
		public List<BaseGridColumn> Columns { get { return _columns; } }
		/// <summary>
		/// Options of the table rendered as part of this Grid control.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		public TableOptions Table { get { return _table; } }
		///// <summary>
		///// Show headers generated by Grid. Note: Header-Template will be shown regardless.
		///// </summary>
		//public bool ShowHeader { get; set; }
		/// <summary>
		/// Options used to determine how the header is rendered.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		public GridItemOptions HeaderOptions { get { return this._headerOptions; } }
		///// <summary>
		///// Show footers generated by Grid. Note: Footer-Template will be shown regardless.
		///// </summary>

		//public bool ShowFooter { get; set; }
		/// <summary>
		/// Controls the way the footer is rendered.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		public GridItemOptions FooterOptions { get { return this._footerOptions; } }
		/// <summary>
		/// Controls the way a view mode table row is rendered.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		public GridItemOptions ViewItemOptions { get { return this._viewItemOptions; } }
		/// <summary>
		/// Controls the way an edit mode table row is rendered.
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		public GridItemOptions EditItemOptions { get { return this._editItemOptions; } }
		#endregion
		#region METHODS
		#endregion
		#endregion
		#region INTERNAL
		#region VARS
		List<BaseGridColumn> _columns = new List<BaseGridColumn>();
		GridItemOptions
			_headerOptions = new GridItemOptions()
			, _footerOptions = new GridItemOptions()
			, _viewItemOptions = new GridItemOptions()
			, _editItemOptions = new GridItemOptions();
		TableOptions _table = new TableOptions();
		Control _headerContainer, _footerContainer;
		#endregion
		#region PROPS
		#endregion
		#region METHODS
		/// <summary>
		/// Init.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);

			this.ParseRenderedItems.Client = "$Grid.Grid_ParseRenderedItems";
		}
		protected override void Init_Templates()
		{
			this.Init_Header();
			this.Init_Footer();
			this.Item_Items();

			base.Init_Templates();
		}
		protected override void Init_Template_Defaults()
		{
		}
		private void Init_Header()
		{
			this.Init_Replace(this.Header.Container, ref this._headerContainer);

			StringBuilder sbBeginTag = new StringBuilder("<table");
			if (this.Table.CellPadding != 1)
				sbBeginTag.AppendFormat(" cellpadding=\"{0}\"", this.Table.CellPadding);
			if (this.Table.CellSpacing != 2)
				sbBeginTag.AppendFormat(" cellspacing=\"{0}\"", this.Table.CellSpacing);
			if (!string.IsNullOrEmpty(this.Table.Align))
				sbBeginTag.AppendFormat(" align=\"{0}\"", this.Table.Align);
			if (!string.IsNullOrEmpty(this.Table.Style))
				sbBeginTag.AppendFormat(" style=\"{0}\"", this.Table.Style);
			if (!string.IsNullOrEmpty(this.Table.CssClass))
				sbBeginTag.AppendFormat(" class=\"{0}\"", this.Table.CssClass);
			sbBeginTag.Append(">");
			this._headerContainer.AppendLiteral(sbBeginTag.ToString());

			if (this.HeaderOptions.Visible)
			{
				//if (this.Header.Template != null)
				//{
					this._headerContainer.AppendLiteral("<thead>");
					this._headerContainer.Controls.Add(Header.Container);
					this._headerContainer.AppendLiteral("</thead>");
				//}

				this.CreateItem(Header.Container, GridColumnVisibility.Any, HeaderOptions, "th", c => c.Header, c => c.CreateHeader);
			}

			this._headerContainer.AppendLiteral("<tbody ItemsContainer=\"1\">");
		}
		private void Init_Footer()
		{
			Init_Replace(this.Footer.Container, ref this._footerContainer);

			this._footerContainer.AppendLiteral("</tbody>");

			if (this.FooterOptions.Visible)
			{
				//if (this.Footer.Template != null)
				//{
					this._footerContainer.AppendLiteral("<tfoot>");
					this._footerContainer.Controls.Add(Footer.Container);
					this._footerContainer.AppendLiteral("</tfoot>");
				//}

				this.CreateItem(Footer.Container, GridColumnVisibility.Any, FooterOptions, "th", c => c.Footer, c => c.CreateFooter);
			}

			this._footerContainer.AppendLiteral("</table>");
		}
		private void Init_Replace(Control oldCtl, ref Control newCtl)
		{
			int index = this.Controls.IndexOf(oldCtl);

			newCtl = new Control();
			this.Controls.RemoveAt(index);
			this.Controls.AddAt(index, newCtl);
		}
		private void Item_Items()
		{
			this.CreateItem(ViewItem.Container, GridColumnVisibility.ViewMode, ViewItemOptions, "td", c => c.ViewCell, c => c.CreateViewItem);
			this.CreateItem(EditItem.Container, GridColumnVisibility.EditMode, EditItemOptions, "td", c => c.EditCell, c => c.CreateEditItem);
		}
		/// <summary>
		/// Registers <see cref="Script.ElementSearch"/> and Grid.js.
		/// </summary>
		protected internal override void RegisterIncludes(IncludeCollection includes)
		{
			base.RegisterIncludes(includes);

			includes.Add(Script.ElementSearch);
			includes.Add(Script.FieldBinding);
			includes.Add(new ScriptResourceInclude("TA.Turbo.Res.JS.Grid.js", typeof(Grid)));
		}
		void CreateItem(Control container, GridColumnVisibility columnVisibility, GridItemOptions options, string tag, Func<BaseGridColumn, StyledElement> getStyles, Func<BaseGridColumn, Action<Control, Grid>> getCreator)
		{
			Control cont = new Control();
			foreach (BaseGridColumn c in Columns)
			{
				if ((c.Visibility & columnVisibility) == columnVisibility)
				{
					StyledElement se = getStyles(c);
					cont.AppendLiteral(string.Format("<{0} class=\"{1}\" style=\"{2}{3}\">"
						, tag
						, se.CssClass, se.Style
						, se.Visible ? "" : ";display:none;"
						));
					getCreator(c)(cont, this);
					cont.AppendLiteral(string.Format("</{0}>", tag));
				}
			}
			if (options.SameRow)
			{
				container.InsertLiteral(0, string.Format("<tr class=\"{0}\" style=\"{1}\">", options.CssClass, options.Style));
				if (options.GridFirst)
					container.Controls.AddAt(1, cont);
				else
					container.Controls.Add(cont);
				container.AppendLiteral("</tr>");
			}
			else
			{
				cont.InsertLiteral(0, string.Format("<tr class=\"{0}\" style=\"{1}\">", options.CssClass, options.Style));
				cont.AppendLiteral("</tr>");
				if (options.GridFirst)
					container.Controls.AddAt(0, cont);
				else
					container.Controls.Add(cont);
			}
		}
		#endregion
		#endregion
	}
}